import qs from 'qs'
import crypto from 'crypto'
import base64url from 'base64url'
import uuid from '@/utils/uuid'
import storage from '@/utils/storage'
import { revoke } from '@/api/oauth2'

const state = () => ({
  codeVerifier: storage.get('codeVerifier'),
  code: storage.get('code'),
  token: storage.get('token') || {},
})

const mutations = {
  SET_CODE_VERIFIER(state, codeVerifier) {
    storage.set('codeVerifier', codeVerifier)
    state.codeVerifier = codeVerifier
  },
  CLEAR_CODE_VERIFIER(state) {
    storage.remove('codeVerifier')
    state.codeVerifier = null
  },
  SET_CODE(state, code) {
    storage.set('code', code)
    state.code = code
  },
  CLEAR_CODE(state) {
    storage.remove('code')
    state.code = null
  },
  SET_TOKEN(state, token) {
    storage.set('token', token)
    state.token = token
  },
  CLEAR_TOKEN(state) {
    storage.remove('token')
    state.token = {}
  },
}

const actions = {
  gotoAuthCenter({ commit }) {
    let codeVerifier = uuid()
    const hash = crypto.createHash('sha256')
    hash.update(codeVerifier)
    commit('SET_CODE_VERIFIER', codeVerifier)

    let params = {
      client_id: window.client.clientId,
      response_type: 'code',
      redirect_uri: window.client.redirectUri,
      code_challenge: base64url.encode(hash.digest()),
      code_challenge_method: 'S256',
    }

    window.location.href =
      window.client.authCenterUrl + '?' + qs.stringify(params)
  },
  tokenRevoke({ state, commit }) {
    revoke({
      client_id: window.client.clientId,
      code_verifier: state.codeVerifier,
      token: state.token.access_token,
      grant_type: 'authorization_code',
      code: state.code,
    }).then(() => {
      setTimeout(() => {
        commit('CLEAR_CODE_VERIFIER')
        commit('CLEAR_CODE')
        commit('CLEAR_ACCESS_TOKEN')
      }, 200)
    })
  },
}

export default {
  namespaced: true,
  state: state,
  actions: actions,
  mutations: mutations,
}
